@ctrl-ui/react 0.9.16 → 0.9.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/action-bar.d.ts +2 -2
- package/dist/action-bar.js +34 -15
- package/dist/activity.d.ts +1 -1
- package/dist/activity.js +1 -1
- package/dist/audio-device-select.js +1 -1
- package/dist/audio-recorder.js +1 -1
- package/dist/blocks/agent-run-sidebar.js +1 -1
- package/dist/blocks/agent-run.js +1 -1
- package/dist/blocks/coding-agent.js +1 -1
- package/dist/blocks/design-canvas-inspector.js +1 -1
- package/dist/blocks/design-canvas.js +1 -1
- package/dist/blocks/discussion.js +1 -1
- package/dist/blocks/file-explorer.js +1 -1
- package/dist/blocks/settings.js +1 -1
- package/dist/blocks/theme-toggle.js +1 -1
- package/dist/chat-composer-attachment.js +1 -1
- package/dist/chat-composer.js +1 -1
- package/dist/chat-layout.js +1 -1
- package/dist/context.js +1 -1
- package/dist/filter-bar/parts.js +1 -1
- package/dist/inline-citation.js +1 -1
- package/dist/knob-contracts/sidebar-knobs.d.ts +1 -1
- package/dist/knob-contracts/sidebar-knobs.js +7 -0
- package/dist/markdown-editor/context.d.ts +2 -0
- package/dist/markdown-editor/drag-handle.js +1 -1
- package/dist/markdown-editor/extensions.d.ts +14 -4
- package/dist/markdown-editor/extensions.js +39 -34
- package/dist/markdown-editor/suggestions.js +4 -5
- package/dist/markdown-editor/toolbar.d.ts +1 -1
- package/dist/markdown-editor/toolbar.js +5 -6
- package/dist/markdown-editor.d.ts +7 -1
- package/dist/markdown-editor.js +16 -6
- package/dist/source-badge.js +1 -1
- package/dist/styles/index.css +1 -0
- package/dist/styles/recipes/action-bar.css +12 -3
- package/dist/styles/recipes/popup-controls.css +3 -3
- package/dist/styles/recipes/resizable.css +15 -0
- package/dist/styles/recipes/sidebar-panes.css +192 -0
- package/dist/styles/recipes/sidebar-parts.css +61 -3
- package/dist/task-list.js +1 -1
- package/dist/tool-approval.js +1 -1
- package/dist/ui/accordion.js +1 -1
- package/dist/ui/breadcrumb.js +1 -1
- package/dist/ui/code.js +1 -1
- package/dist/ui/dropzone.js +1 -1
- package/dist/ui/emoji-picker.js +1 -1
- package/dist/ui/flow.js +1 -1
- package/dist/ui/hover-card.d.ts +3 -1
- package/dist/ui/hover-card.js +2 -2
- package/dist/ui/infinite-canvas.js +1 -1
- package/dist/ui/pagination.js +1 -1
- package/dist/ui/resizable.d.ts +3 -1
- package/dist/ui/resizable.js +3 -1
- package/dist/ui/rich-tooltip.js +1 -1
- package/dist/ui/sidebar-menu.js +6 -6
- package/dist/ui/sidebar-mobile.js +1 -1
- package/dist/ui/sidebar-provider.d.ts +2 -0
- package/dist/ui/sidebar-provider.js +7 -1
- package/dist/ui/sidebar.d.ts +12 -0
- package/dist/ui/sidebar.js +34 -9
- package/dist/ui/spinner.js +1 -1
- package/dist/ui/stepper.js +1 -1
- package/dist/ui/toast.js +1 -1
- package/dist/ui/tree.js +1 -1
- package/dist/user-ask.js +1 -1
- package/package.json +1 -1
package/dist/action-bar.d.ts
CHANGED
|
@@ -41,10 +41,10 @@ export type ActionBarCopyProps = ActionBarItemBaseProps & {
|
|
|
41
41
|
copyFailedLabel?: string;
|
|
42
42
|
resetDelay?: number;
|
|
43
43
|
};
|
|
44
|
-
export declare function ActionBarCopy({ value, children, copiedChildren, copiedAriaLabel, copyFailedLabel, resetDelay, disabled, onClick, ...props }: ActionBarCopyProps): import("react").JSX.Element;
|
|
44
|
+
export declare function ActionBarCopy({ value, children, copiedChildren, copiedAriaLabel, copyFailedLabel, resetDelay, disabled, onClick, "aria-label": ariaLabel, ...props }: ActionBarCopyProps): import("react").JSX.Element;
|
|
45
45
|
export type ActionBarEditProps = ActionBarItemBaseProps & {
|
|
46
46
|
value?: ActionBarCopyValue;
|
|
47
47
|
children?: NonNullable<ReactNode>;
|
|
48
48
|
};
|
|
49
|
-
export declare function ActionBarEdit({ value, children, disabled, onClick, ...props }: ActionBarEditProps): import("react").JSX.Element;
|
|
49
|
+
export declare function ActionBarEdit({ value, children, disabled, onClick, "aria-label": ariaLabel, ...props }: ActionBarEditProps): import("react").JSX.Element;
|
|
50
50
|
//#endregion
|
package/dist/action-bar.js
CHANGED
|
@@ -5,6 +5,7 @@ import { Button } from "./ui/button.js";
|
|
|
5
5
|
import { LiveStatus } from "./ui/live-status.js";
|
|
6
6
|
import { Swap, SwapItem } from "./ui/swap.js";
|
|
7
7
|
import { Toolbar } from "@base-ui/react/toolbar";
|
|
8
|
+
import { CheckIcon, CopyIcon, PencilIcon } from "lucide-react";
|
|
8
9
|
import { createContext, useContext } from "react";
|
|
9
10
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
10
11
|
//#region src/action-bar.tsx
|
|
@@ -48,7 +49,7 @@ function ActionBarItem({ icon, children, active, disabled, ...props }) {
|
|
|
48
49
|
})
|
|
49
50
|
});
|
|
50
51
|
}
|
|
51
|
-
function ActionBarCopy({ value, children
|
|
52
|
+
function ActionBarCopy({ value, children, copiedChildren, copiedAriaLabel = "Copied to clipboard", copyFailedLabel = "Couldn't copy. Select the text and copy it manually.", resetDelay = 1200, disabled, onClick, "aria-label": ariaLabel, ...props }) {
|
|
52
53
|
const { copyValue: contextCopyValue, onCopy, onCopyError } = useContext(ActionBarContext);
|
|
53
54
|
const copyValue = value ?? contextCopyValue;
|
|
54
55
|
const { status, copyToClipboard } = useCopyToClipboard({
|
|
@@ -71,27 +72,36 @@ function ActionBarCopy({ value, children = "Copy", copiedChildren = "Copied", co
|
|
|
71
72
|
let copyStatus = "";
|
|
72
73
|
if (copied) copyStatus = copiedAriaLabel;
|
|
73
74
|
else if (status === "failed") copyStatus = copyFailedLabel;
|
|
74
|
-
|
|
75
|
+
const isIconOnly = children === void 0;
|
|
76
|
+
const swap = /* @__PURE__ */ jsxs(Swap, {
|
|
77
|
+
value: copied ? "copied" : "idle",
|
|
78
|
+
children: [/* @__PURE__ */ jsx(SwapItem, {
|
|
79
|
+
value: "idle",
|
|
80
|
+
children: children ?? /* @__PURE__ */ jsx(CopyIcon, { "aria-hidden": "true" })
|
|
81
|
+
}), /* @__PURE__ */ jsx(SwapItem, {
|
|
82
|
+
value: "copied",
|
|
83
|
+
"aria-hidden": "true",
|
|
84
|
+
children: copiedChildren ?? (isIconOnly ? /* @__PURE__ */ jsx(CheckIcon, { "aria-hidden": "true" }) : "Copied")
|
|
85
|
+
})]
|
|
86
|
+
});
|
|
87
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [isIconOnly ? /* @__PURE__ */ jsx(ActionBarItem, {
|
|
88
|
+
"aria-label": ariaLabel ?? "Copy",
|
|
89
|
+
icon: swap,
|
|
90
|
+
disabled: disabled ?? !copyValue,
|
|
91
|
+
onClick: handleClick,
|
|
92
|
+
...props
|
|
93
|
+
}) : /* @__PURE__ */ jsxs(ActionBarItem, {
|
|
94
|
+
"aria-label": ariaLabel,
|
|
75
95
|
disabled: disabled ?? !copyValue,
|
|
76
96
|
onClick: handleClick,
|
|
77
97
|
...props,
|
|
78
|
-
children: [/* @__PURE__ */
|
|
79
|
-
value: copied ? "copied" : "idle",
|
|
80
|
-
children: [/* @__PURE__ */ jsx(SwapItem, {
|
|
81
|
-
value: "idle",
|
|
82
|
-
children
|
|
83
|
-
}), /* @__PURE__ */ jsx(SwapItem, {
|
|
84
|
-
value: "copied",
|
|
85
|
-
"aria-hidden": "true",
|
|
86
|
-
children: copiedChildren
|
|
87
|
-
})]
|
|
88
|
-
}), copied ? /* @__PURE__ */ jsx("span", {
|
|
98
|
+
children: [swap, copied ? /* @__PURE__ */ jsx("span", {
|
|
89
99
|
className: "sr-only",
|
|
90
100
|
children
|
|
91
101
|
}) : null]
|
|
92
102
|
}), /* @__PURE__ */ jsx(LiveStatus, { message: copyStatus })] });
|
|
93
103
|
}
|
|
94
|
-
function ActionBarEdit({ value, children
|
|
104
|
+
function ActionBarEdit({ value, children, disabled, onClick, "aria-label": ariaLabel, ...props }) {
|
|
95
105
|
const { copyValue, editValue: contextEditValue, onEdit, onEditError } = useContext(ActionBarContext);
|
|
96
106
|
const editValue = value ?? contextEditValue ?? copyValue;
|
|
97
107
|
async function handleClick(event) {
|
|
@@ -105,8 +115,17 @@ function ActionBarEdit({ value, children = "Edit", disabled, onClick, ...props }
|
|
|
105
115
|
onEditError?.(error);
|
|
106
116
|
}
|
|
107
117
|
}
|
|
118
|
+
const itemDisabled = disabled ?? (editValue === void 0 || !onEdit);
|
|
119
|
+
if (children === void 0) return /* @__PURE__ */ jsx(ActionBarItem, {
|
|
120
|
+
"aria-label": ariaLabel ?? "Edit",
|
|
121
|
+
icon: /* @__PURE__ */ jsx(PencilIcon, { "aria-hidden": "true" }),
|
|
122
|
+
disabled: itemDisabled,
|
|
123
|
+
onClick: handleClick,
|
|
124
|
+
...props
|
|
125
|
+
});
|
|
108
126
|
return /* @__PURE__ */ jsx(ActionBarItem, {
|
|
109
|
-
|
|
127
|
+
"aria-label": ariaLabel,
|
|
128
|
+
disabled: itemDisabled,
|
|
110
129
|
onClick: handleClick,
|
|
111
130
|
...props,
|
|
112
131
|
children
|
package/dist/activity.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { ActivityKnobStyle } from "./knob-contracts/activity-knobs.js";
|
|
2
2
|
import { CollapsibleContent, CollapsibleProps, CollapsibleTrigger } from "./ui/collapsible.js";
|
|
3
3
|
import { ScrollAreaProps } from "./ui/scroll-area.js";
|
|
4
|
-
import { CSSProperties, ComponentProps, ReactNode } from "react";
|
|
5
4
|
import { ChevronRight } from "lucide-react";
|
|
5
|
+
import { CSSProperties, ComponentProps, ReactNode } from "react";
|
|
6
6
|
//#region src/activity.d.ts
|
|
7
7
|
export type ActivityState = "pending" | "running" | "waiting" | "success" | "error";
|
|
8
8
|
export type ActivityKind = "default" | "tool" | "reasoning" | "signal";
|
package/dist/activity.js
CHANGED
|
@@ -3,9 +3,9 @@ import { cn } from "./lib/cn.js";
|
|
|
3
3
|
import { LiveStatus } from "./ui/live-status.js";
|
|
4
4
|
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "./ui/collapsible.js";
|
|
5
5
|
import { ScrollArea } from "./ui/scroll-area.js";
|
|
6
|
+
import { Check, ChevronRight, CircleAlert, CircleDashed, CirclePause, LoaderCircle } from "lucide-react";
|
|
6
7
|
import { createContext, useContext } from "react";
|
|
7
8
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
-
import { Check, ChevronRight, CircleAlert, CircleDashed, CirclePause, LoaderCircle } from "lucide-react";
|
|
9
9
|
//#region src/activity.tsx
|
|
10
10
|
const activityStatusLabels = {
|
|
11
11
|
pending: "Pending",
|
|
@@ -3,9 +3,9 @@ import { cn } from "./lib/cn.js";
|
|
|
3
3
|
import { Button } from "./ui/button.js";
|
|
4
4
|
import { Select, SelectContent, SelectItem, SelectTrigger } from "./ui/select.js";
|
|
5
5
|
import { Text } from "./ui/typography.js";
|
|
6
|
+
import { MicIcon, Volume2Icon } from "lucide-react";
|
|
6
7
|
import { createContext, use, useState } from "react";
|
|
7
8
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
-
import { MicIcon, Volume2Icon } from "lucide-react";
|
|
9
9
|
//#region src/audio-device-select.tsx
|
|
10
10
|
const AUDIO_DEVICE_COPY = {
|
|
11
11
|
input: {
|
package/dist/audio-recorder.js
CHANGED
|
@@ -5,9 +5,9 @@ import { LiveStatus } from "./ui/live-status.js";
|
|
|
5
5
|
import { AudioVisualizer } from "./audio-visualizer.js";
|
|
6
6
|
import { useAudioRecorder } from "./hooks/use-audio-recorder.js";
|
|
7
7
|
import { formatAudioRecorderDuration } from "./lib/format-audio-recorder-duration.js";
|
|
8
|
+
import { CheckIcon, MicIcon, XIcon } from "lucide-react";
|
|
8
9
|
import { createContext, use, useRef, useState } from "react";
|
|
9
10
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
10
|
-
import { CheckIcon, MicIcon, XIcon } from "lucide-react";
|
|
11
11
|
//#region src/audio-recorder.tsx
|
|
12
12
|
const AudioRecorderContext = createContext(null);
|
|
13
13
|
const AudioRecorderTriggerRefContext = createContext(null);
|
|
@@ -4,8 +4,8 @@ import { useSidebar } from "../ui/sidebar-provider.js";
|
|
|
4
4
|
import { SidebarGroup, SidebarGroupLabel, SidebarMenu, SidebarMenuButton, SidebarMenuItem } from "../ui/sidebar-menu.js";
|
|
5
5
|
import { Sidebar, SidebarContent, SidebarFooter, SidebarHeader, SidebarRail } from "../ui/sidebar.js";
|
|
6
6
|
import { agentRunStatusLabels } from "./agent-run-status.js";
|
|
7
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
7
|
import { BotIcon, CheckIcon, CircleAlertIcon, CircleDashedIcon, CirclePauseIcon, CircleSlashIcon, LoaderCircleIcon, PlusIcon } from "lucide-react";
|
|
8
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
9
9
|
//#region src/blocks/agent-run-sidebar.tsx
|
|
10
10
|
const runStatusIcons = {
|
|
11
11
|
running: /* @__PURE__ */ jsx(LoaderCircleIcon, {
|
package/dist/blocks/agent-run.js
CHANGED
|
@@ -11,9 +11,9 @@ import { agentRunStatusColors, agentRunStatusLabels, agentRunStepLabels } from "
|
|
|
11
11
|
import { AgentRunSidebar } from "./agent-run-sidebar.js";
|
|
12
12
|
import { Card, CardAction, CardContent, CardHeader } from "../ui/card.js";
|
|
13
13
|
import { Timeline, TimelineContent, TimelineDescription, TimelineIndicator, TimelineItem, TimelineMeta, TimelineSeparator, TimelineTitle } from "../ui/timeline.js";
|
|
14
|
+
import { Check, Circle, CircleAlert, CircleDashed, CirclePause, LoaderCircle } from "lucide-react";
|
|
14
15
|
import { createContext, useContext, useId } from "react";
|
|
15
16
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
16
|
-
import { Check, Circle, CircleAlert, CircleDashed, CirclePause, LoaderCircle } from "lucide-react";
|
|
17
17
|
//#region src/blocks/agent-run.tsx
|
|
18
18
|
const AgentRunLayoutContext = createContext("viewport");
|
|
19
19
|
function useHeadingLevels() {
|
|
@@ -8,8 +8,8 @@ import { SidebarProvider, useSidebar } from "../ui/sidebar-provider.js";
|
|
|
8
8
|
import { SidebarGroup, SidebarGroupLabel, SidebarMenu, SidebarMenuButton, SidebarMenuItem, SidebarMenuSub } from "../ui/sidebar-menu.js";
|
|
9
9
|
import { Sidebar, SidebarContent, SidebarFooter, SidebarHeader, SidebarInset, SidebarRail, SidebarTrigger } from "../ui/sidebar.js";
|
|
10
10
|
import { Item, ItemContent, ItemDescription, ItemMedia, ItemTitle } from "../ui/item.js";
|
|
11
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
12
11
|
import { BotIcon, ChevronRightIcon, CircleIcon, FolderIcon, PlusIcon, SearchIcon } from "lucide-react";
|
|
12
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
13
13
|
//#region src/blocks/coding-agent.tsx
|
|
14
14
|
function CodingAgentBlock({ appName = "Agent", brand, sidebarTop, navigation = [], projects, activeTaskId, activeTaskTitle = "New task", onNavigationSelect, onTaskSelect, onNewTask, onSearch, headerActions, sidebarFooter, children, layout = "viewport", className, style, ...props }) {
|
|
15
15
|
const providerStyle = {
|
|
@@ -11,9 +11,9 @@ import { ColorPickerEyeDropper, ColorPickerInput } from "../ui/color-picker-valu
|
|
|
11
11
|
import { ColorPicker, ColorPickerContent, ColorPickerTrigger } from "../ui/color-picker.js";
|
|
12
12
|
import { Empty, EmptyDescription, EmptyHeader, EmptyTitle } from "../ui/empty.js";
|
|
13
13
|
import { Toggle } from "../ui/toggle.js";
|
|
14
|
+
import { BlendIcon, EyeIcon, EyeOffIcon, Link2Icon, MinusIcon, PlusIcon, RotateCwIcon, SquareRoundCornerIcon, Unlink2Icon } from "lucide-react";
|
|
14
15
|
import { useState } from "react";
|
|
15
16
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
16
|
-
import { BlendIcon, EyeIcon, EyeOffIcon, Link2Icon, MinusIcon, PlusIcon, RotateCwIcon, SquareRoundCornerIcon, Unlink2Icon } from "lucide-react";
|
|
17
17
|
//#region src/blocks/design-canvas-inspector.tsx
|
|
18
18
|
const WHOLE_NUMBER_FORMAT = {
|
|
19
19
|
useGrouping: false,
|
|
@@ -10,9 +10,9 @@ import { DesignCanvasInspector } from "./design-canvas-inspector.js";
|
|
|
10
10
|
import { Toolbar, ToolbarButton, ToolbarGroup, ToolbarSeparator } from "../ui/toolbar.js";
|
|
11
11
|
import { InfiniteCanvas, InfiniteCanvasContent, InfiniteCanvasControls, InfiniteCanvasItem } from "../ui/infinite-canvas.js";
|
|
12
12
|
import { ResizableFloatingPanel } from "../ui/resizable.js";
|
|
13
|
+
import { CircleIcon, FrameIcon, HandIcon, LayersIcon, MousePointer2Icon, SlidersHorizontalIcon, SquareIcon, TypeIcon } from "lucide-react";
|
|
13
14
|
import { useRef, useState } from "react";
|
|
14
15
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
15
|
-
import { CircleIcon, FrameIcon, HandIcon, LayersIcon, MousePointer2Icon, SlidersHorizontalIcon, SquareIcon, TypeIcon } from "lucide-react";
|
|
16
16
|
//#region src/blocks/design-canvas.tsx
|
|
17
17
|
const TOOLS = [
|
|
18
18
|
{
|
|
@@ -6,9 +6,9 @@ import { ChatMessageReplies } from "../chat-message/social.js";
|
|
|
6
6
|
import { ChatMessage, ChatMessageActions, ChatMessageAuthor, ChatMessageAvatar, ChatMessageBody, ChatMessageContent, ChatMessageFooter, ChatMessageHeader, ChatMessageRow, ChatMessageTime } from "../chat-message.js";
|
|
7
7
|
import { Markdown } from "../ui/markdown.js";
|
|
8
8
|
import { Kbd, KbdGroup } from "../ui/kbd.js";
|
|
9
|
+
import { CornerDownRightIcon } from "lucide-react";
|
|
9
10
|
import { Suspense, lazy, useState } from "react";
|
|
10
11
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
11
|
-
import { CornerDownRightIcon } from "lucide-react";
|
|
12
12
|
//#region src/blocks/discussion.tsx
|
|
13
13
|
const DiscussionMarkdownInput = lazy(() => import("./discussion-markdown-input.js"));
|
|
14
14
|
function DiscussionComposer({ label, placeholder, submitLabel = "Post", secondaryAction, hint = /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs(KbdGroup, { children: [/* @__PURE__ */ jsx(Kbd, { children: "⌘" }), /* @__PURE__ */ jsx(Kbd, { children: "Enter" })] }), /* @__PURE__ */ jsx("span", { children: "to post" })] }), autoFocus, format = "plain", onUploadImage, mentions, onSubmit, ...props }) {
|
|
@@ -15,9 +15,9 @@ import { ResizableHandle, ResizablePanel, ResizablePanelGroup } from "../ui/resi
|
|
|
15
15
|
import { DropdownMenu, DropdownMenuContent, DropdownMenuTrigger } from "../ui/dropdown-menu.js";
|
|
16
16
|
import { groupFileExplorerItems, orderFileExplorerEntries, resolveFileExplorer, searchFileExplorer } from "./file-explorer-data.js";
|
|
17
17
|
import { Breadcrumb, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator } from "../ui/breadcrumb.js";
|
|
18
|
+
import { ChevronLeftIcon, ChevronRightIcon, FileIcon, FolderIcon, MoreHorizontalIcon, SearchIcon, XIcon } from "lucide-react";
|
|
18
19
|
import { Fragment, useEffect, useId, useRef, useState } from "react";
|
|
19
20
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
20
|
-
import { ChevronLeftIcon, ChevronRightIcon, FileIcon, FolderIcon, MoreHorizontalIcon, SearchIcon, XIcon } from "lucide-react";
|
|
21
21
|
//#region src/blocks/file-explorer.tsx
|
|
22
22
|
function defaultSearchStatusLabel(count, query) {
|
|
23
23
|
if (count === 0) return `No results for “${query}”`;
|
package/dist/blocks/settings.js
CHANGED
|
@@ -13,9 +13,9 @@ import { Input } from "../ui/input.js";
|
|
|
13
13
|
import { Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle } from "../ui/empty.js";
|
|
14
14
|
import { searchSettings } from "./settings-data.js";
|
|
15
15
|
import { Field, FieldContent, FieldDescription, FieldGroup, FieldLabel, FieldLegend, FieldSet } from "../ui/field.js";
|
|
16
|
+
import { ArrowLeftIcon, SearchIcon, XIcon } from "lucide-react";
|
|
16
17
|
import { useEffect, useId, useState } from "react";
|
|
17
18
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
18
|
-
import { ArrowLeftIcon, SearchIcon, XIcon } from "lucide-react";
|
|
19
19
|
//#region src/blocks/settings.tsx
|
|
20
20
|
function SettingsBlock({ pages, activePageId, defaultActivePageId, onActivePageChange, backAction, searchPlaceholder = "Search settings", searchLabel = "Search settings", layout = "viewport", className, style, ...props }) {
|
|
21
21
|
const [internalPageId, setInternalPageId] = useState(defaultActivePageId ?? pages[0]?.id);
|
|
@@ -3,9 +3,9 @@ import { Button } from "../ui/button.js";
|
|
|
3
3
|
import { Text } from "../ui/typography.js";
|
|
4
4
|
import { DropdownMenu, DropdownMenuContent, DropdownMenuLabel, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuTrigger } from "../ui/dropdown-menu.js";
|
|
5
5
|
import { Switch } from "../ui/switch.js";
|
|
6
|
+
import { ChevronDownIcon, MonitorIcon, MoonIcon, SunIcon } from "lucide-react";
|
|
6
7
|
import { useId } from "react";
|
|
7
8
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
-
import { ChevronDownIcon, MonitorIcon, MoonIcon, SunIcon } from "lucide-react";
|
|
9
9
|
//#region src/blocks/theme-toggle.tsx
|
|
10
10
|
const systemThemeOption = {
|
|
11
11
|
value: "system",
|
|
@@ -4,9 +4,9 @@ import { Button } from "./ui/button.js";
|
|
|
4
4
|
import { LiveStatus } from "./ui/live-status.js";
|
|
5
5
|
import { ScrollArea } from "./ui/scroll-area.js";
|
|
6
6
|
import { Spinner } from "./ui/spinner.js";
|
|
7
|
+
import { XIcon } from "lucide-react";
|
|
7
8
|
import { createContext, useContext, useLayoutEffect, useState } from "react";
|
|
8
9
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
9
|
-
import { XIcon } from "lucide-react";
|
|
10
10
|
//#region src/chat-composer-attachment.tsx
|
|
11
11
|
const ChatComposerAttachmentContext = createContext(null);
|
|
12
12
|
function useChatComposerAttachmentContext() {
|
package/dist/chat-composer.js
CHANGED
|
@@ -5,9 +5,9 @@ import { useSkin } from "./skin-provider.js";
|
|
|
5
5
|
import { Button } from "./ui/button.js";
|
|
6
6
|
import { Spinner } from "./ui/spinner.js";
|
|
7
7
|
import { useChatComposer } from "./hooks/use-chat-composer.js";
|
|
8
|
+
import { Square } from "lucide-react";
|
|
8
9
|
import { createContext, useContext, useEffect, useRef } from "react";
|
|
9
10
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
10
|
-
import { Square } from "lucide-react";
|
|
11
11
|
//#region src/chat-composer.tsx
|
|
12
12
|
const ChatComposerContext = createContext(null);
|
|
13
13
|
function useChatComposerContext() {
|
package/dist/chat-layout.js
CHANGED
|
@@ -6,10 +6,10 @@ import { LiveStatus } from "./ui/live-status.js";
|
|
|
6
6
|
import { ScrollArea } from "./ui/scroll-area.js";
|
|
7
7
|
import { ChatThreadAnnounceContext } from "./hooks/use-chat-message.js";
|
|
8
8
|
import { useChatThreadScroll } from "./hooks/use-chat-thread-scroll.js";
|
|
9
|
+
import { ArrowDown } from "lucide-react";
|
|
9
10
|
import { createContext, useContext, useState } from "react";
|
|
10
11
|
import { useRender } from "@base-ui/react/use-render";
|
|
11
12
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
12
|
-
import { ArrowDown } from "lucide-react";
|
|
13
13
|
//#region src/chat-layout.tsx
|
|
14
14
|
const chromeSizing = {
|
|
15
15
|
panel: "mx-auto min-h-[640px] max-w-3xl",
|
package/dist/context.js
CHANGED
|
@@ -4,9 +4,9 @@ import { Button } from "./ui/button.js";
|
|
|
4
4
|
import { ScrollArea } from "./ui/scroll-area.js";
|
|
5
5
|
import { deriveContextModel } from "./context-model.js";
|
|
6
6
|
import { Popover, PopoverClose, PopoverContent, PopoverDescription, PopoverTitle, PopoverTrigger } from "./ui/popover.js";
|
|
7
|
+
import { X } from "lucide-react";
|
|
7
8
|
import { createContext, useContext, useId, useMemo } from "react";
|
|
8
9
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
9
|
-
import { X } from "lucide-react";
|
|
10
10
|
//#region src/context.tsx
|
|
11
11
|
const ContextValueContext = createContext(null);
|
|
12
12
|
function useContextValue() {
|
package/dist/filter-bar/parts.js
CHANGED
|
@@ -4,10 +4,10 @@ import { Button } from "../ui/button.js";
|
|
|
4
4
|
import { useFilterBarContext } from "./context.js";
|
|
5
5
|
import { describeFilter, formatFilterValue } from "./model.js";
|
|
6
6
|
import { FilterBarEditor, FilterBarInlineInput } from "./editor.js";
|
|
7
|
+
import { PlusIcon, XIcon } from "lucide-react";
|
|
7
8
|
import { useEffect, useId, useRef } from "react";
|
|
8
9
|
import { useRender } from "@base-ui/react/use-render";
|
|
9
10
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
10
|
-
import { PlusIcon, XIcon } from "lucide-react";
|
|
11
11
|
//#region src/filter-bar/parts.tsx
|
|
12
12
|
function chipSegments(item, field, operator, draft) {
|
|
13
13
|
const segments = [{
|
package/dist/inline-citation.js
CHANGED
|
@@ -4,9 +4,9 @@ import { Button } from "./ui/button.js";
|
|
|
4
4
|
import { LiveStatus } from "./ui/live-status.js";
|
|
5
5
|
import { Popover, PopoverContent, PopoverTrigger } from "./ui/popover.js";
|
|
6
6
|
import { SourceFavicon, sourceHostname } from "./source-badge.js";
|
|
7
|
+
import { ArrowLeft, ArrowRight, ExternalLink } from "lucide-react";
|
|
7
8
|
import { createContext, useContext, useRef, useState } from "react";
|
|
8
9
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
9
|
-
import { ArrowLeft, ArrowRight, ExternalLink } from "lucide-react";
|
|
10
10
|
//#region src/inline-citation.tsx
|
|
11
11
|
const defaultViewSourcesLabel = (count) => count === 1 ? "view 1 source" : `view ${count} sources`;
|
|
12
12
|
const defaultPositionLabel = (position, count) => `Source ${position} of ${count}`;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
//#region src/knob-contracts/sidebar-knobs.d.ts
|
|
2
|
-
export declare const sidebarKnobs: readonly ["--cui-sidebar-nav-height", "--cui-sidebar-nav-background", "--cui-sidebar-nav-foreground", "--cui-sidebar-nav-border-color", "--cui-sidebar-nav-border-width", "--cui-sidebar-nav-shadow", "--cui-sidebar-nav-item-radius", "--cui-sidebar-nav-item-active-background", "--cui-sidebar-nav-item-active-foreground", "--cui-sidebar-nav-gap", "--cui-sidebar-menu-badge-height", "--cui-sidebar-menu-badge-background", "--cui-sidebar-menu-badge-foreground", "--cui-sidebar-header-border-width", "--cui-sidebar-header-border-color", "--cui-sidebar-rail-divider-background", "--cui-sidebar-wrapper-background", "--cui-sidebar-wrapper-background-image", "--cui-sidebar-inner-background", "--cui-sidebar-inner-border-color", "--cui-sidebar-inner-background-image", "--cui-sidebar-inner-backdrop-filter", "--cui-sidebar-container-border-width", "--cui-sidebar-inner-border-width", "--cui-sidebar-inner-radius", "--cui-sidebar-inner-shadow", "--cui-sidebar-header-background", "--cui-sidebar-header-shadow", "--cui-sidebar-inset-background", "--cui-sidebar-inset-background-image", "--cui-sidebar-inset-shadow", "--cui-sidebar-inset-border-color", "--cui-sidebar-inset-border-width", "--cui-sidebar-inset-radius", "--cui-sidebar-inset-inset", "--cui-sidebar-menu-button-radius", "--cui-sidebar-group-label-foreground", "--cui-sidebar-menu-button-foreground", "--cui-sidebar-menu-button-hover-background", "--cui-sidebar-menu-button-hover-foreground", "--cui-sidebar-menu-button-hover-shadow", "--cui-sidebar-menu-button-active-background", "--cui-sidebar-menu-button-active-foreground", "--cui-sidebar-menu-button-active-shadow", "--cui-sidebar-menu-button-track-active-foreground", "--cui-sidebar-menu-button-height", "--cui-sidebar-menu-button-padding-block", "--cui-sidebar-menu-button-padding-inline", "--cui-sidebar-menu-button-font-size", "--cui-sidebar-menu-button-font-weight", "--cui-sidebar-menu-button-active-font-weight", "--cui-sidebar-group-label-font-size", "--cui-sidebar-group-label-font-weight", "--cui-sidebar-group-label-letter-spacing", "--cui-sidebar-group-label-text-transform", "--cui-sidebar-group-label-padding", "--cui-sidebar-skip-link-background", "--cui-sidebar-skip-link-foreground", "--cui-sidebar-skip-link-radius", "--cui-sidebar-skip-link-shadow", "--cui-sidebar-menu-button-background", "--cui-sidebar-menu-button-shadow"];
|
|
2
|
+
export declare const sidebarKnobs: readonly ["--cui-sidebar-nav-height", "--cui-sidebar-nav-background", "--cui-sidebar-nav-foreground", "--cui-sidebar-nav-border-color", "--cui-sidebar-nav-border-width", "--cui-sidebar-nav-shadow", "--cui-sidebar-nav-item-radius", "--cui-sidebar-nav-item-active-background", "--cui-sidebar-nav-item-active-foreground", "--cui-sidebar-nav-gap", "--cui-sidebar-icon-rail-border-width", "--cui-sidebar-icon-rail-border-color", "--cui-sidebar-raised-background", "--cui-sidebar-raised-border-width", "--cui-sidebar-raised-border-color", "--cui-sidebar-raised-radius", "--cui-sidebar-raised-shadow", "--cui-sidebar-menu-badge-height", "--cui-sidebar-menu-badge-background", "--cui-sidebar-menu-badge-foreground", "--cui-sidebar-header-border-width", "--cui-sidebar-header-border-color", "--cui-sidebar-rail-divider-background", "--cui-sidebar-wrapper-background", "--cui-sidebar-wrapper-background-image", "--cui-sidebar-inner-background", "--cui-sidebar-inner-border-color", "--cui-sidebar-inner-background-image", "--cui-sidebar-inner-backdrop-filter", "--cui-sidebar-container-border-width", "--cui-sidebar-inner-border-width", "--cui-sidebar-inner-radius", "--cui-sidebar-inner-shadow", "--cui-sidebar-header-background", "--cui-sidebar-header-shadow", "--cui-sidebar-inset-background", "--cui-sidebar-inset-background-image", "--cui-sidebar-inset-shadow", "--cui-sidebar-inset-border-color", "--cui-sidebar-inset-border-width", "--cui-sidebar-inset-radius", "--cui-sidebar-inset-inset", "--cui-sidebar-menu-button-radius", "--cui-sidebar-group-label-foreground", "--cui-sidebar-menu-button-foreground", "--cui-sidebar-menu-button-hover-background", "--cui-sidebar-menu-button-hover-foreground", "--cui-sidebar-menu-button-hover-shadow", "--cui-sidebar-menu-button-active-background", "--cui-sidebar-menu-button-active-foreground", "--cui-sidebar-menu-button-active-shadow", "--cui-sidebar-menu-button-track-active-foreground", "--cui-sidebar-menu-button-height", "--cui-sidebar-menu-button-padding-block", "--cui-sidebar-menu-button-padding-inline", "--cui-sidebar-menu-button-font-size", "--cui-sidebar-menu-button-font-weight", "--cui-sidebar-menu-button-active-font-weight", "--cui-sidebar-group-label-font-size", "--cui-sidebar-group-label-font-weight", "--cui-sidebar-group-label-letter-spacing", "--cui-sidebar-group-label-text-transform", "--cui-sidebar-group-label-padding", "--cui-sidebar-skip-link-background", "--cui-sidebar-skip-link-foreground", "--cui-sidebar-skip-link-radius", "--cui-sidebar-skip-link-shadow", "--cui-sidebar-menu-button-background", "--cui-sidebar-menu-button-shadow"];
|
|
3
3
|
export type SidebarKnobStyle = Partial<Record<(typeof sidebarKnobs)[number], string>>;
|
|
4
4
|
//#endregion
|
|
@@ -10,6 +10,13 @@ const sidebarKnobs = [
|
|
|
10
10
|
"--cui-sidebar-nav-item-active-background",
|
|
11
11
|
"--cui-sidebar-nav-item-active-foreground",
|
|
12
12
|
"--cui-sidebar-nav-gap",
|
|
13
|
+
"--cui-sidebar-icon-rail-border-width",
|
|
14
|
+
"--cui-sidebar-icon-rail-border-color",
|
|
15
|
+
"--cui-sidebar-raised-background",
|
|
16
|
+
"--cui-sidebar-raised-border-width",
|
|
17
|
+
"--cui-sidebar-raised-border-color",
|
|
18
|
+
"--cui-sidebar-raised-radius",
|
|
19
|
+
"--cui-sidebar-raised-shadow",
|
|
13
20
|
"--cui-sidebar-menu-badge-height",
|
|
14
21
|
"--cui-sidebar-menu-badge-background",
|
|
15
22
|
"--cui-sidebar-menu-badge-foreground",
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { MarkdownUrlPolicy } from "./extensions.js";
|
|
1
2
|
import { MarkdownImageUpload } from "./uploads.js";
|
|
2
3
|
import { Editor } from "@tiptap/core";
|
|
3
4
|
//#region src/markdown-editor/context.d.ts
|
|
@@ -7,6 +8,7 @@ export type MarkdownEditorContextValue = {
|
|
|
7
8
|
source: boolean;
|
|
8
9
|
markdown: string;
|
|
9
10
|
sourceRequired: boolean;
|
|
11
|
+
isUrlAllowed: MarkdownUrlPolicy;
|
|
10
12
|
setSource: (source: boolean) => void;
|
|
11
13
|
setMarkdown: (value: string) => void;
|
|
12
14
|
setContentAttributes: (attributes: Record<string, string>) => void;
|
|
@@ -3,9 +3,9 @@ import { Button } from "../ui/button.js";
|
|
|
3
3
|
import { LiveStatus } from "../ui/live-status.js";
|
|
4
4
|
import { useMarkdownEditor } from "./context.js";
|
|
5
5
|
import { createDragPreview } from "./drag-preview.js";
|
|
6
|
+
import { GripVerticalIcon } from "lucide-react";
|
|
6
7
|
import { useEffect, useRef, useState } from "react";
|
|
7
8
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
-
import { GripVerticalIcon } from "lucide-react";
|
|
9
9
|
import { NodeSelection } from "@tiptap/pm/state";
|
|
10
10
|
import { closeHistory } from "@tiptap/pm/history";
|
|
11
11
|
//#region src/markdown-editor/drag-handle.tsx
|
|
@@ -1,10 +1,20 @@
|
|
|
1
|
-
import { Extension, JSONContent, Node } from "@tiptap/core";
|
|
1
|
+
import { Extension, Extensions, JSONContent, Node } from "@tiptap/core";
|
|
2
2
|
import { MarkdownManager } from "@tiptap/markdown";
|
|
3
3
|
//#region src/markdown-editor/extensions.d.ts
|
|
4
4
|
export declare function isEditorUrl(value: string, image?: boolean): boolean;
|
|
5
|
+
export type MarkdownUrlKind = "link" | "image";
|
|
6
|
+
/** Decides which URLs the editor keeps. Content with a refused URL stays in source mode, so nothing is dropped. */
|
|
7
|
+
export type MarkdownUrlPolicy = (url: string, kind: MarkdownUrlKind) => boolean;
|
|
8
|
+
/** Web apps only keep URLs that still resolve after a reload: HTTP(S), mailto, root-relative paths and anchors. */
|
|
9
|
+
export declare const persistentUrlPolicy: MarkdownUrlPolicy;
|
|
10
|
+
export type MarkdownExtensionOptions = {
|
|
11
|
+
/** Extra TipTap extensions, applied after the built-in Markdown set. */
|
|
12
|
+
extensions?: Extensions;
|
|
13
|
+
isUrlAllowed?: MarkdownUrlPolicy;
|
|
14
|
+
};
|
|
5
15
|
export declare const ImageUpload: Node<any, any>;
|
|
6
|
-
export declare function markdownExtensions(): (
|
|
7
|
-
export declare function createMarkdownCodec(): MarkdownManager;
|
|
8
|
-
export declare function requiresMarkdownSource(markdown: string, codec: MarkdownManager): boolean;
|
|
16
|
+
export declare function markdownExtensions({ extensions, isUrlAllowed }?: MarkdownExtensionOptions): (import("@tiptap/core").AnyExtension | Extension<import("@tiptap/markdown").MarkdownExtensionOptions, import("@tiptap/markdown").MarkdownExtensionStorage> | Extension<import("@tiptap/starter-kit").StarterKitOptions, any> | Extension<import("@tiptap/extension-table").TableKitOptions, any> | Node<any, any> | Node<import("@tiptap/extension-image").ImageOptions, any> | Node<import("@tiptap/extension-paragraph").ParagraphOptions, any> | Node<import("@tiptap/extension-list").TaskItemOptions, any> | Node<import("@tiptap/extension-list").TaskListOptions, any>)[];
|
|
17
|
+
export declare function createMarkdownCodec(options?: MarkdownExtensionOptions): MarkdownManager;
|
|
18
|
+
export declare function requiresMarkdownSource(markdown: string, codec: MarkdownManager, isUrlAllowed?: MarkdownUrlPolicy): boolean;
|
|
9
19
|
export declare function hasMarkdownContent(document: JSONContent): boolean;
|
|
10
20
|
//#endregion
|
|
@@ -42,27 +42,31 @@ function isEditorUrl(value, image = false) {
|
|
|
42
42
|
return false;
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
}
|
|
45
|
+
/** Web apps only keep URLs that still resolve after a reload: HTTP(S), mailto, root-relative paths and anchors. */
|
|
46
|
+
const persistentUrlPolicy = (url, kind) => isEditorUrl(url, kind === "image");
|
|
47
|
+
function safeImage(isUrlAllowed) {
|
|
48
|
+
return Image.extend({
|
|
49
|
+
renderMarkdown: (node) => {
|
|
50
|
+
const src = String(node.attrs?.src ?? "").replace(/[()]/g, (character) => `\\${character}`);
|
|
51
|
+
const alt = String(node.attrs?.alt ?? "").replace(/[\\[\]]/g, (character) => `\\${character}`);
|
|
52
|
+
const title = String(node.attrs?.title ?? "").replace(/[\\"]/g, (character) => `\\${character}`);
|
|
53
|
+
return title ? `` : ``;
|
|
54
|
+
},
|
|
55
|
+
addAttributes() {
|
|
56
|
+
return {
|
|
57
|
+
...this.parent?.(),
|
|
58
|
+
src: {
|
|
59
|
+
default: null,
|
|
60
|
+
parseHTML: (element) => {
|
|
61
|
+
const src = element.getAttribute("src") ?? "";
|
|
62
|
+
return isUrlAllowed(src, "image") ? src : null;
|
|
63
|
+
},
|
|
64
|
+
renderHTML: (attributes) => ({ src: isUrlAllowed(attributes.src ?? "", "image") ? attributes.src : void 0 })
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
}
|
|
66
70
|
const MarkdownParagraph = Paragraph.extend({ parseMarkdown: (token, helpers) => {
|
|
67
71
|
const content = helpers.parseInline(token.tokens ?? []);
|
|
68
72
|
const first = content[0];
|
|
@@ -88,19 +92,19 @@ const ImageUpload = Node.create({
|
|
|
88
92
|
],
|
|
89
93
|
renderMarkdown: () => ""
|
|
90
94
|
});
|
|
91
|
-
function markdownExtensions() {
|
|
95
|
+
function markdownExtensions({ extensions = [], isUrlAllowed = persistentUrlPolicy } = {}) {
|
|
92
96
|
return [
|
|
93
97
|
StarterKit.configure({
|
|
94
98
|
underline: false,
|
|
95
99
|
paragraph: false,
|
|
96
100
|
link: {
|
|
97
101
|
openOnClick: false,
|
|
98
|
-
isAllowedUri: (url) =>
|
|
102
|
+
isAllowedUri: (url) => isUrlAllowed(url, "link")
|
|
99
103
|
}
|
|
100
104
|
}),
|
|
101
105
|
MarkdownParagraph,
|
|
102
106
|
MarkdownHeadings,
|
|
103
|
-
|
|
107
|
+
safeImage(isUrlAllowed).configure({
|
|
104
108
|
allowBase64: false,
|
|
105
109
|
inline: true
|
|
106
110
|
}),
|
|
@@ -111,11 +115,12 @@ function markdownExtensions() {
|
|
|
111
115
|
}),
|
|
112
116
|
TableKit.configure({ table: { resizable: false } }),
|
|
113
117
|
ImageUpload,
|
|
114
|
-
Markdown
|
|
118
|
+
Markdown,
|
|
119
|
+
...extensions
|
|
115
120
|
];
|
|
116
121
|
}
|
|
117
|
-
function createMarkdownCodec() {
|
|
118
|
-
return new MarkdownManager({ extensions: markdownExtensions() });
|
|
122
|
+
function createMarkdownCodec(options) {
|
|
123
|
+
return new MarkdownManager({ extensions: markdownExtensions(options) });
|
|
119
124
|
}
|
|
120
125
|
const supportedTokens = /* @__PURE__ */ new Set([
|
|
121
126
|
"space",
|
|
@@ -140,17 +145,17 @@ const supportedTokens = /* @__PURE__ */ new Set([
|
|
|
140
145
|
"taskList",
|
|
141
146
|
"taskItem"
|
|
142
147
|
]);
|
|
143
|
-
function unsupportedToken(value) {
|
|
144
|
-
if (Array.isArray(value)) return value.some(unsupportedToken);
|
|
148
|
+
function unsupportedToken(value, isUrlAllowed) {
|
|
149
|
+
if (Array.isArray(value)) return value.some((item) => unsupportedToken(item, isUrlAllowed));
|
|
145
150
|
if (typeof value !== "object" || value === null) return false;
|
|
146
151
|
if ("type" in value && typeof value.type === "string") {
|
|
147
152
|
if (!supportedTokens.has(value.type)) return true;
|
|
148
|
-
if ((value.type === "image" || value.type === "link") && "href" in value && typeof value.href === "string" && !
|
|
153
|
+
if ((value.type === "image" || value.type === "link") && "href" in value && typeof value.href === "string" && !isUrlAllowed(value.href, value.type)) return true;
|
|
149
154
|
}
|
|
150
|
-
return Object.values(value).some(unsupportedToken);
|
|
155
|
+
return Object.values(value).some((item) => unsupportedToken(item, isUrlAllowed));
|
|
151
156
|
}
|
|
152
|
-
function requiresMarkdownSource(markdown, codec) {
|
|
153
|
-
return unsupportedToken(codec.instance.lexer(markdown));
|
|
157
|
+
function requiresMarkdownSource(markdown, codec, isUrlAllowed = persistentUrlPolicy) {
|
|
158
|
+
return unsupportedToken(codec.instance.lexer(markdown), isUrlAllowed);
|
|
154
159
|
}
|
|
155
160
|
function hasMarkdownContent(document) {
|
|
156
161
|
if (document.type === "image") return true;
|
|
@@ -158,4 +163,4 @@ function hasMarkdownContent(document) {
|
|
|
158
163
|
return document.content?.some(hasMarkdownContent) ?? false;
|
|
159
164
|
}
|
|
160
165
|
//#endregion
|
|
161
|
-
export { ImageUpload, createMarkdownCodec, hasMarkdownContent, isEditorUrl, markdownExtensions, requiresMarkdownSource };
|
|
166
|
+
export { ImageUpload, createMarkdownCodec, hasMarkdownContent, isEditorUrl, markdownExtensions, persistentUrlPolicy, requiresMarkdownSource };
|
|
@@ -2,12 +2,11 @@
|
|
|
2
2
|
import { LiveStatus } from "../ui/live-status.js";
|
|
3
3
|
import { isComposingKey, useTriggerMenu } from "../hooks/use-trigger-menu.js";
|
|
4
4
|
import { useMarkdownEditor } from "./context.js";
|
|
5
|
-
import { isEditorUrl } from "./extensions.js";
|
|
6
5
|
import { detectTrigger } from "../lib/trigger-detect.js";
|
|
7
6
|
import { TriggerMenu, TriggerMenuEmpty, TriggerMenuIcon, TriggerMenuItem, TriggerMenuList } from "../ui/trigger-menu.js";
|
|
7
|
+
import { Heading1Icon, Heading2Icon, Heading3Icon, ListChecksIcon, ListIcon, ListOrderedIcon, MinusIcon, QuoteIcon, SquareCodeIcon, TextIcon, UserIcon } from "lucide-react";
|
|
8
8
|
import { useEffect, useEffectEvent, useRef } from "react";
|
|
9
9
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
10
|
-
import { Heading1Icon, Heading2Icon, Heading3Icon, ListChecksIcon, ListIcon, ListOrderedIcon, MinusIcon, QuoteIcon, SquareCodeIcon, TextIcon, UserIcon } from "lucide-react";
|
|
11
10
|
//#region src/markdown-editor/suggestions.tsx
|
|
12
11
|
const blockCommands = [
|
|
13
12
|
{
|
|
@@ -94,7 +93,7 @@ function readTrigger(editor) {
|
|
|
94
93
|
}
|
|
95
94
|
function MarkdownEditorSuggestions({ mentions = [], onMentionSelect }) {
|
|
96
95
|
const activeItem = useRef(null);
|
|
97
|
-
const { editor, disabled, source } = useMarkdownEditor();
|
|
96
|
+
const { editor, disabled, source, isUrlAllowed } = useMarkdownEditor();
|
|
98
97
|
const enabled = Boolean(editor) && !disabled && !source;
|
|
99
98
|
const controller = useTriggerMenu({
|
|
100
99
|
triggers: [{
|
|
@@ -113,7 +112,7 @@ function MarkdownEditorSuggestions({ mentions = [], onMentionSelect }) {
|
|
|
113
112
|
to: match.end
|
|
114
113
|
};
|
|
115
114
|
if (match.char === "/" && item.command) item.command(editor.chain().focus().deleteRange(range)).run();
|
|
116
|
-
if (match.char === "@" && item.href &&
|
|
115
|
+
if (match.char === "@" && item.href && isUrlAllowed(item.href, "link")) {
|
|
117
116
|
editor.chain().focus().insertContentAt(range, [{
|
|
118
117
|
type: "text",
|
|
119
118
|
text: `@${item.label}`,
|
|
@@ -212,7 +211,7 @@ function MarkdownEditorSuggestions({ mentions = [], onMentionSelect }) {
|
|
|
212
211
|
children: controller.items.map((item, index) => /* @__PURE__ */ jsxs(TriggerMenuItem, {
|
|
213
212
|
id: controller.optionId(index),
|
|
214
213
|
active: index === controller.activeIndex,
|
|
215
|
-
disabled: item.disabled || item.href !== void 0 && !
|
|
214
|
+
disabled: item.disabled || item.href !== void 0 && !isUrlAllowed(item.href, "link"),
|
|
216
215
|
ref: index === controller.activeIndex ? activeItem : void 0,
|
|
217
216
|
onPointerMove: () => controller.setActiveIndex(index),
|
|
218
217
|
onClick: () => controller.select(item),
|